﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ch6
{
    class Program
    {
        private static bool _isRunning = false;
        private static object _locker = new object();
        private static int total = 0;
        static void Main(string[] args)
        {
            // 1. 应用场景: 1. 计算密集型, 2. IO 密集型
            // 2. 异步, 多线程, 并发
            // 3. 在尽可能所有场景使用 Task 而不是 Thread

            //var demo = new Demo() { Name = "张三", Age = 18 };
            //demo.Show();

            //Test1(demo);
            //Test2();

            //Test4();

            //demo.ShowLock();

            //var task = Test5();
            //task.Start();

            //while (total <= 100000)
            //{
            //    await Task.Delay(100);
            //}

            //_isRunning = false;

            Test6();

            Console.WriteLine($"当前线程编号: {Thread.CurrentThread.ManagedThreadId}: Hello World!");
        }

        /// <summary>
        ///  Thread
        /// </summary>
        /// <param name="demo"></param>
        static void Test1(Demo demo)
        {
            var thread = new Thread(new ThreadStart(() => demo.Show()));
            thread.Start();

            var parameterizedThread = new Thread(new ParameterizedThreadStart(demo.Show));
            parameterizedThread.Start(new { Name = "李四", Age = 20 });
        }

        /// <summary>
        /// 线程池
        /// </summary>
        static void Test2()
        {
            //ThreadPool.QueueUserWorkItem(new WaitCallback(demo.Show));

            var index = 10;
            var events = new ManualResetEvent[index];
            for (int i = 0; i < index; i++)
            {
                events[i] = new ManualResetEvent(false);
                var demo = new Demo() { Name = "张三", Age = 20 };
                ThreadPool.QueueUserWorkItem(new WaitCallback(demo.Show), new { Name = "李四", Age = 20 + i, ManualResetEvent = events[i] });
            }

            WaitHandle.WaitAll(events);
            Console.WriteLine($"当前线程编号: {Thread.CurrentThread.ManagedThreadId}: Hello World!");
        }

        /// <summary>
        /// Task
        /// </summary>
        static Task Test3(Demo demo)
        {
            Console.WriteLine($"当前线程编号: {Thread.CurrentThread.ManagedThreadId}: Hello World!");
            new TaskFactory().StartNew(() => demo.Show());
            return Task.Run(() => demo.Show());

            //var parameteriedTask = new Task(x => demo.Show(x), new { Name = "李四", Age = 20 });
            //parameteriedTask.Start();
            //await parameteriedTask;
            //await new Task(x => demo.Show(x), new { Name = "李四", Age = 20 });
        }

        /// <summary>
        /// 并发
        /// </summary>
        static void Test4()
        {
            Parallel.For(0, 10000, x =>
            {
                total += 10;
            });

            Console.WriteLine(total);
        }

        static Task Test5()
        {
            return new Task(async () =>
            {
                var index = 10000;
                while (_isRunning)
                {
                    try
                    {
                        //do something
                        index--;
                        total += 10;
                    }
                    catch (Exception ex)
                    {
                        //
                    }
                    finally
                    {
                        if (index <= 0)
                        {
                            await Task.Delay(1000);
                        }
                    }
                }
            }, TaskCreationOptions.LongRunning);
        }

        /// <summary>
        /// 任务组
        /// </summary>
        static void Test6()
        {
            var tasks = new List<Task>();
            for (int i = 0; i < 1000; i++)
            {
                var task = new Task(() =>
                {
                    //total += 100;
                    lock (_locker)
                    {
                        total += 100;
                    }
                });
                tasks.Add(task);
                task.Start();
            }

            Task.WaitAll(tasks.ToArray());
            Console.WriteLine(total);
        }
    }

    class Demo
    {
        private static int total = 0;
        private static object _locker = new object();
        public string Name { get; set; }
        public int Age { get; set; }
        //public ManualResetEvent ManualResetEvent { get; set; }

        public void Show()
        {
            //Thread.Sleep(300);
            //Console.WriteLine($"当前线程编号: {Thread.CurrentThread.ManagedThreadId}: the {Name} now {Age} years old!");
            //ManualResetEvent.Set();
        }

        public void Show(object obj)
        {
            dynamic demo = obj;
            Name = demo.Name;
            Age = demo.Age;
            //ManualResetEvent = demo.ManualResetEvent;
            Thread.Sleep(100);
            Console.WriteLine($"当前线程编号: {Thread.CurrentThread.ManagedThreadId}: the {Name} now {Age} years old!");
            //ManualResetEvent.Set();
        }

        public void ShowLock()
        {
            Parallel.For(0, 10000, x =>
            {
                lock (_locker)
                {
                    total += 10;
                }
            });

            Console.WriteLine(total);
        }
    }
}
